home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_03_04 / 3n04052a < prev    next >
Text File  |  1992-02-09  |  19KB  |  630 lines

  1. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=Begin Listing4-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2. /*****************************************************/
  3. /* listmenu.c                                        */
  4. /* -- Implements a popup menu with a scrollable      */
  5. /*    ListBox.                                       */
  6. /*****************************************************/
  7.  
  8. /*****************************************************/
  9. /* Header files.                                     */
  10. /*****************************************************/
  11. #include <windows.h>
  12. #include "listmenu.h"
  13.  
  14. /*****************************************************/
  15. /* Constants.                                        */
  16. /*****************************************************/
  17. #define imdsNil     -1  /* Undefined menu index. */
  18. #define cbMenuMax   256 /* Max. length of MenuItem. */
  19. #define szMenuClass "#32768"    /* Menu classname. */
  20. #define szListClass "ListBox"   /* LBox classname. */
  21. #define szFilter    "LFilter"   /* Filter classname. */
  22.  
  23. /*****************************************************/
  24. /* Types.                                            */
  25. /*****************************************************/
  26. typedef struct
  27.     {
  28.     int     cidm;           /* # items in menu. */
  29.     int     dx, dy;         /* Size of menu. */
  30.     int     idm;            /* Index in MenuBar. */
  31.     HMENU   hmnu;           /* Original popup menu. */
  32.     HWND    hwnd;           /* ListBox window. */
  33.     WORD    rgidm[1];       /* MenuItem id array */
  34.     } MDS;                  /* Menu DeScriptor. */
  35. typedef MDS FAR *   LPMDS;
  36. typedef HANDLE      HMDS;
  37. typedef HMDS FAR *  LRGHMDS;
  38.  
  39. /*****************************************************/
  40. /* Globals.                                          */
  41. /*****************************************************/
  42.  
  43. HANDLE  hrghmds;        /* Handle to array of menus. */
  44. int     cmds;           /* Number of menus. */
  45. int     imdsDown;       /* Dropped popup menu. */
  46. HWND    hwndMenu;       /* Popup menu window. */
  47. HWND    hwndMain;       /* App's main window. */
  48. HMENU   hmnuTop;        /* App's MenuBar. */
  49. FARPROC lpfnMenuFilter; /* Popup menu subclasser. */
  50. FARPROC lpfnMenu;       /* Popup menu window proc. */
  51. FARPROC lpfnMain;       /* App's main window proc. */
  52. FARPROC lpfnMainFilter; /* Subclasser for above. */
  53. FARPROC lpfnListFilter; /* Subclasser for ListBox. */
  54. FARPROC lpfnList;
  55. BOOL    fButtonDown;    /* Buttoned down in list? */
  56.  
  57. /*****************************************************/
  58. /* Private Prototypes.                               */
  59. /*****************************************************/
  60. void                CloseListMenu(void);
  61. void                DestroyMenuImds(int);
  62. BOOL FAR  PASCAL    FEnumWnd(HWND, LONG);
  63. void                GetMdsImds(MDS *, int);
  64. WORD                IdmFromIidmImds(int, int);
  65. int                 ImdsFromIdm(WORD);
  66. LONG FAR  PASCAL    ListFilter(HWND, WORD, WORD, LONG);
  67. LONG FAR  PASCAL    MainFilter(HWND, WORD, WORD, LONG);
  68. LONG FAR  PASCAL    MenuFilter(HWND, WORD, WORD, LONG);
  69. void                RemoveListMenu(BOOL);
  70.  
  71. /*****************************************************/
  72. /* Routines.                                         */
  73. /*****************************************************/
  74.  
  75. BOOL
  76. FInitListMenu(BOOL fFirst, HWND hwnd)
  77. /*****************************************************/
  78. /* -- Initialize the list menu module.               */
  79. /* -- hwnd       : Window containing MenuBar.        */
  80. /* -- szMenuList : Name of menu list of popups.      */
  81. /*****************************************************/
  82.     {
  83.     FARPROC     lpfn;   /* EnumWindows() callback. */
  84.     HANDLE      hins;   /* App's instance. */
  85.     WNDCLASS    wcs;    /* Our own ListBox class. */
  86.  
  87.     hwndMain = hwnd;
  88.     if ((hmnuTop = GetMenu(hwnd)) == NULL)
  89.         return FALSE;
  90.  
  91.     /* Get the popup menu handle so we can subclass */
  92.     /* it at will. */
  93.     hins = GetWindowWord(hwnd, GWW_HINSTANCE);
  94.     if ((lpfn = MakeProcInstance(FEnumWnd, hins)) ==
  95.       NULL)
  96.         return FALSE;
  97.  
  98.     EnumWindows(lpfn, 0L);
  99.     FreeProcInstance(lpfn);
  100.     if (hwndMenu == NULL)
  101.         return FALSE;
  102.  
  103.     lpfnMenu =
  104.       (FARPROC)GetWindowLong(hwndMenu, GWL_WNDPROC);
  105.     if ((lpfnMenuFilter = MakeProcInstance(
  106.       (FARPROC)MenuFilter, hins)) == NULL)
  107.         return FALSE;
  108.  
  109.     /* Subclass the app's main window. */
  110.     lpfnMain =
  111.       (FARPROC)GetWindowLong(hwndMain, GWL_WNDPROC);
  112.     if ((lpfnMainFilter = MakeProcInstance(
  113.       (FARPROC)MainFilter, hins)) == NULL)
  114.         return FALSE;
  115.     SetWindowLong(hwndMain, GWL_WNDPROC,
  116.       (LONG)lpfnMainFilter);
  117.  
  118.     /* Create a our version of the ListBox class. */
  119.     if (!GetClassInfo(NULL, szListClass, &wcs))
  120.         return FALSE;
  121.     lpfnList = (FARPROC)wcs.lpfnWndProc;
  122.  
  123.     if (fFirst)
  124.         {
  125.         wcs.lpfnWndProc = ListFilter;
  126.         wcs.hInstance = hins;
  127.         wcs.lpszClassName = szFilter;
  128.         if (!RegisterClass(&wcs))
  129.             return FALSE;
  130.         }
  131.  
  132.     imdsDown = imdsNil;
  133.     return TRUE;
  134.     }
  135.  
  136. BOOL FAR PASCAL
  137. FEnumWnd(HWND hwnd, LONG lwp)
  138. /*****************************************************/
  139. /* -- EnumWindows() callback to get popup menu       */
  140. /*    window handle.                                 */
  141. /*****************************************************/
  142.     {
  143.     char    szBuf[40];
  144.  
  145.     GetClassName(hwnd, szBuf, sizeof szBuf);
  146.     if (!lstrcmp(szBuf, szMenuClass))
  147.         {
  148.         hwndMenu = hwnd;
  149.         return FALSE;
  150.         }
  151.     return TRUE;
  152.     }
  153.  
  154. void
  155. CloseListMenu(void)
  156. /*****************************************************/
  157. /* -- Close the list menu module.                    */
  158. /*****************************************************/
  159.     {
  160.     int     imds;
  161.  
  162.     if (cmds == 0)
  163.         return; /* Nothing to do. */
  164.  
  165.     /* Destroy all list menus. */
  166.     for (imds = 0; imds < cmds; imds++)
  167.         DestroyMenuImds(imds);
  168.  
  169.     /* Remove filters. */
  170.     if (lpfnMenu != NULL)
  171.         {
  172.         if (IsWindow(hwndMenu))
  173.             SetWindowLong(hwndMenu, GWL_WNDPROC,
  174.               (LONG)lpfnMenu);
  175.         lpfnMenu = NULL;
  176.         }
  177.     if (lpfnMenuFilter != NULL)
  178.         {
  179.         FreeProcInstance(lpfnMenuFilter);
  180.         lpfnMenuFilter = NULL;
  181.         }
  182.  
  183.     if (lpfnMain != NULL && IsWindow(hwndMain))
  184.         SetWindowLong(hwndMain, GWL_WNDPROC,
  185.           (LONG)lpfnMain);
  186.     if (lpfnMainFilter != NULL)
  187.         {
  188.         FreeProcInstance(lpfnMainFilter);
  189.         lpfnMainFilter = NULL;
  190.         }
  191.  
  192.     /* Restore state and free menu table array. */
  193.     hmnuTop = NULL;
  194.     hwndMenu = hwndMain = NULL;
  195.     GlobalFree(hrghmds);
  196.     hrghmds = NULL;
  197.     cmds = 0;
  198.     }
  199.  
  200. BOOL
  201. FAssignMenu(WORD idm, int dy)
  202. /*****************************************************/
  203. /* -- Assign a list menu to the given MenuItem.      */
  204. /* -- The strings and command values for the list    */
  205. /*    menu are extracted from the given popup menu.  */
  206. /* -- Return TRUE for success, FALSE for failure.    */
  207. /* -- idm       : MenuItem id.                       */
  208. /* -- dy        : Height of the menu.                */
  209. /*****************************************************/
  210.     {
  211.     int     imds;
  212.     HMENU   hmnu;
  213.     HMDS    hmds    = NULL;
  214.     LPMDS   lpmds   = NULL;
  215.     HDC     hdc     = NULL;
  216.     int     iidm, cidm;
  217.     BOOL    fVal    = FALSE;
  218.     HANDLE  hins;
  219.  
  220.     /* See if a list menu for this popup already */
  221.     /* exists.  If not, grow (or allocate if for the */
  222.     /* first time) the list menu table array.  If */
  223.     /* a list menu already exists, destroy it, but */
  224.     /* reuse its slot in the array. */
  225.     if ((imds = ImdsFromIdm(idm)) == imdsNil)
  226.         {
  227.         /* Grow menu array. */
  228.         if (cmds == 0)
  229.             {
  230.             if ((hrghmds = GlobalAlloc(
  231.               GMEM_MOVEABLE | GMEM_ZEROINIT,
  232.               sizeof(HMDS))) == NULL)
  233.                 goto FAssignMenuError;
  234.  
  235.             cmds = 1;
  236.             imds = 0;
  237.             }
  238.         else
  239.             {
  240.             HANDLE  hrghmdsNew;
  241.  
  242.             imds = cmds++;
  243.             if ((hrghmdsNew = GlobalReAlloc(hrghmds, 
  244.                 cmds * sizeof(HMDS),
  245.                 GMEM_MOVEABLE | GMEM_ZEROINIT))
  246.               == NULL)
  247.                 goto FAssignMenuErro